#ifndef _CCSV_READER_H_
#define _CCSV_READER_H_
#include <stdio.h>
#include <string.h>
#include "toolLib.h"
#include "csvRecord.h"
typedef enum
{
    CCSVReadErrorReaderNoError,
    CCSVReadErrorReaderAttrError,
    CCSVReadErrorArgErr,
    CCSVReadErrorReadEOF,
    CCSVReadErrorReadError,
    CCSVReadErrorFieldNumError,
    CCSVReadErrorFieldFormatError,
    CCSVReadErrorFieldOutOfCacheSize,
} CCSVReadError;

typedef struct csvReader *CsvReader;
CsvReader
NewCCSVReader(FILE *fp);
void ReleaseCCSVReader(CsvReader reader);
CsvRecord CCSVRead(CsvReader reader);
void ResetCCSVReader(CsvReader reader);
void skipReadOneLine(CsvReader r);
//csvReader is the core struct during reading csv file.
//the reader realizes based on go/encode/csv,the following is the description of it:
/*
    A Reader reads records from a CSV-encoded file.

    As returned by NewReader, a Reader expects input conforming to RFC 4180.
    The exported fields can be changed to customize the details before the
    first call to Read or ReadAll.

    The Reader converts all \r\n sequences in its input to plain \n,
    including in multiline field values, so that the returned data does
    not depend on which line-ending convention an input file uses.
*/
//fp: use stdio to realize the reading of file
//the arg can't enforce by modify it directly, please call the init func to change them
struct csvReader
{
    //in go lib, developer can use rune to support utf-8, we just accept ASCII
    //comma is the field delimiter.
    //it is set to comma(',') by NewReader.

    char comma;
    //comment, if not 0, is the comment character.Lines beginning with the comment character without preceding whitespace
    //are ignored.With leading whitespace the comment character becomes part of the field, even if TrimLeadingSpace is true.
    //comment must be a valid char and must not be \r, \n, or the Unicode replacement character (0xFFFD).
    //It must also not be equal to comma
    char comment;

    //fieldsPerRecord is the number of expected fields per record.
    //If fieldsPerRecord is positive, Read Requires each record to have the given number of fields.
    //If fieldsPerRecord is 0, Read sets it to the number of the fields in the first record, so that future records must
    //have the same field count.If fieldsPerRecord is negative, no check is made and records may have a variable number of
    //the fields.
    int fieldsPerRecord;

    //if trimLeadingSpace is true, leading white space in a field is ignored.
    //This is done even if the field delimiterm, Comma, is white space.
    BOOL trimLeadingSpace;

    FILE *fp;

    //numLine is the current line being read in the CSV file.
    //if accept error, we can confirm the line number
    int numLine;

    //we initialize the buffer when we call NewCCSVReader
    char *rawBuffer;
    //rawBuffer is a line buffer only used by the readLine method

    //assign the sizeof rawBuffer
    int rawBufferSize;
    int rawLen;

    //the line may be the member of the raw, use lineLen to mark the len of current line
    int lineLen;
    //filedStartPos is every filed pos in recordBuffer.
    char **fieldStartPos;
    //the index of handling field in the line
    int fieldIndex;

    //next field start position
    char *nextFieldStartPos;

    //record error when reading
    CCSVReadError error;
    CsvRecord record;

    //first line
    BOOL firstRecord;
};

#endif
